perm filename SAY3.FAI[SYS,HE] blob sn#129815 filedate 1974-11-14 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00006 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY SAY
C00005 00003	Main speaking loop
C00008 00004	Special control codes
C00010 00005	PHONEME CONVERSION TABLE
C00015 00006	Phoneme modifier table
C00016 ENDMK
C⊗;
ENTRY SAY
TITLE SAY
INTERNAL SAY
EXTERNAL JOBFF

COMMENT⊗	SAIL calling sequence:
PROCEDURE SAY(STRING S)

SAY does an IOPUSH of channel 0, INIT's the voder, does a temporary audio
switch select of the voder channel, speaks out the string, IOPOP's channel 0,
and restores the permanent audio switch mapping.
⊗

IPNT←1		;Input string pointer
OPNT←2		;Output pointer
OBUF←3		;Output buffer (4 9-bit bytes)
LAST←4		;Last phoneme spoken, in case of a modifier.
LINF←5		;Inflection of last phoneme
NBYTES←6	;No. of bytes left in input
CODE←7
TEM←10
PLEVEL←11	;Permanent inflection level
TLEVEL←13	;Temporary level

SP←16		;SAIL pointers
P←17

SAY:	CHNSTS 0,TEM
	MOVEM TEM,STAT#
	TRNN TEM,400000
	JRST NOPUSH
	IOPUSH 0,0
	JRST [	OUTSTR [ASCIZ|No room on I/O PDL -- SAY
|]
		EXIT]
NOPUSH:	MOVEI TEM,0

OPNIT:	INIT 0,410
	  'VOD   '
	  XWD VBUF,0
	  JRST WVODR
	SETSTS 0,10
	MOVEI TEM,BUFR
	EXCH TEM,JOBFF
	OUTBUF 0,1
	MOVEM TEM,JOBFF

	POP SP,IPNT			;Get the string pointer.
	POP SP,NBYTES
	HRRZ NBYTES,NBYTES
	MOVEI PLEVEL,1			;Default inflection is normal.
	MOVE OPNT,[POINT 9,OBUF]
	MOVEI OBUF,0
	MOVEI LAST,0
	MOVE TEM,[607010,,0]		;Temporary AS mapping to voder.
	ADSMAP TEM,

;End of initialization.  Fall through to main loop.
;Main speaking loop

NXTPHN:	MOVE TLEVEL,PLEVEL		;New phoneme - set inf. to permanent.

NXTBYT:	SOJL NBYTES,FINISH		;End of input string?
	ILDB CODE,IPNT			;No.  Get next byte.
	SKIPL CODE,PHNTAB(CODE)
	JRST SPCL			;Special codes have bit 0 off.

REGPHN:	MOVE LAST,CODE			;Save code in case of a modifier.
	MOVE LINF,TLEVEL
	TLNE OPNT,770000		;Is the one-word buffer full?
	JRST PUTIT

	SOSG VBUF+2
	OUTPUT 0,
	IDPB OBUF,VBUF+1
	MOVEI OBUF,0
	MOVE OPNT,[POINT 9,OBUF]

PUTIT:	LDB TEM,[POINT 9,CODE,8]	;Phoneme code is in bits 0:8.
	OR TEM,TLEVEL			;Add the inflection bits,
	IDPB TEM,OPNT			;and stick it in the buffer.
	JRST NXTPHN

SPCL:	JUMPN CODE,(CODE)		;Special code.  Go do it.
	JRST NXTBYT			;Ignore undefined codes.

FINISH:	JUMPE OBUF,FIN1			;All done.
	SOSG VBUF+2
	OUTPUT 0,
	IDPB OBUF,VBUF+1

FIN1:	OUTPUT 0,			;Force the last buffer out.
	MOVSI OBUF,777000		;Output a null phoneme
	SOS VBUF+2			;(forces a wait until the
	IDPB OBUF,VBUF+1		;voder finishes talking)
	OUTPUT 0,
	MOVNI TEM,1
	ADSMAP TEM,			;Restore the permanent AS mapping
	RELEAS 0,			;and the state of I/O.
	MOVE TEM,STAT
	TRNE TEM,400000
	IOPOP 0,0
	JFCL
	POPJ P,

WVODR:					;JUST RETURN
	POP SP,IPNT			;Get the string pointer.
	POP SP,NBYTES
	POPJ P,
;Special control codes

DIG:	JUMPE LAST,NXTBYT		;Digit 1-3...
	LDB CODE,IPNT
	ANDI CODE,3
NXTDIG:	LDB TEM,MODTAB(CODE)		;pick up the modified phoneme from
	JUMPN TEM,PUTDIG		;the last code used.  If zero,
	SOJG CODE,NXTDIG		;decrease the digit.
	JRST NXTBYT			;No modifers allowed.  Ignore it.
PUTDIG:	OR TEM,LINF			;Got the mod.  Add the right inflection,
	CAIN TEM,400			;Avoid EH3 with highest inflection,
	MOVEI TEM,401			;since it hangs the voder
	DPB TEM,OPNT			;put it into the buffer.
	JRST NXTPHN

SETLVL:	HLRZ PLEVEL,CODE		;Absolute level select.
	JRST NXTPHN

UPP:	HLRZ TEM,CODE			;Up permanent inflection...
	SUB PLEVEL,TEM			;subtract the increment,
	JUMPGE PLEVEL,NXTPHN		;cut off at 0.
	MOVEI PLEVEL,0
	JRST NXTPHN

DWNP:	HLRZ TEM,CODE			;Down permanently...
	ADD PLEVEL,TEM			;add the increment,
	CAILE PLEVEL,3			;cut off at 3.
	MOVEI PLEVEL,3
	JRST NXTPHN

UPT:	SOJGE TLEVEL,NXTBYT		;Up temporarily.
	MOVEI TLEVEL,0
	JRST NXTBYT

DWNT:	ADDI TLEVEL,1			;Down temporarily.
	CAILE TLEVEL,3
	MOVEI TLEVEL,3
	JRST NXTBYT

WBRK:	MOVEI PLEVEL,1
	HLLZ CODE,CODE
	TLO CODE,400000
	JRST REGPHN
;PHONEME CONVERSION TABLE
XALL

;Lower-case letters without pronunciation examples are the same
;as upper case

DEFINE P(A) {BYTE (9)400+A,0,0,0}
DEFINE P1(A,B) {BYTE (9)400+A,400+B,0,0}
DEFINE P2(A,B,C) {BYTE (9)400+A,400+B,400+C,0}
DEFINE P3(A,B,C,D) {BYTE(9)400+A,400+B,400+C,400+D}

PHNTAB:
	0		;000
   2,,DWNP		;001 ↓ Down 2 levels
P2 274,310,014		;002 α AW (lAW)
	0		;003
   UPT			;004 ∧ Up for just one
	0		;005
	0		;006
	0		;007

	0		;010
	0		;011
	0		;012
	0		;013
	0		;014
	0		;015
	0		;016
	0		;017

	0		;020
	0		;021
   0,,SETLVL		;022 ∩ Highest pitch
   3,,SETLVL		;023 ∪ Lowest pitch
P2 044,250,020		;024 ∀ AH (fAther)
P  204			;025 ∃ AY (wAve)
	0		;026
	0		;027

   2,,SETLVL		;030 _ Low pitch
	0		;031
	0		;032
	0		;033
	0		;034
	0		;035
	0		;036
   DWNT			;037 ∨ Down for just one

   300000,,WBRK		;040 (SP) Word pause, reset inflection to normal.
	0		;041
P  174			;042 " Comma pause
	0		;043
	0		;044
	0		;045
	0		;046
P  300			;047 ' Word pause

	0		;050
	0		;051
	0		;052
	0		;053
   174000,,WBRK		;054 , Comma pause, reset inflection to normal.
   1,,SETLVL		;055 - normal pitch
	0		;056
   1,,UPP		;057 / Upward

	0		;060
   DIG			;061 1 Duration modifiers
   DIG			;062 2
   DIG			;063 3
	0		;064
	0		;065
	0		;066
	0		;067

	0		;070
	0		;071
	0		;072
	0		;073
	0		;074
	0		;075
	0		;076
	0		;077

	0		;100
P2 004,140,240		;101 A (nAme)
P  160			;102 B
P  010			;103 C (CHair)
P  170			;104 D (Dig)
P1 064,074		;105 E (kEEp)
P  270			;106 F
P  070			;107 G (Go)

P  330			;110 H
P3 344,320,120,220	;111 I (sIx)
P  130			;112 J (Just)
P  230			;113 K
P  030			;114 L
P  060			;115 M
P  260			;116 N (No)
P2 144,254,054		;117 O (nO)

P  244			;120 P
	0		;121
P2 134,324,154		;122 R (fERn)
P  370			;123 S
P  124			;124 T
P1 024,354		;125 U (tOO)
P  360			;126 V
P  264			;127 W

P  234			;130 X (THink)
P1 224,104		;131 Y (Yes)
P  110			;132 Z (Zoo)
	0		;133
   1,,DWNP		;134 \ Downward
	0		;135
   2,,UPP		;136 ↑ Up 2 levels
	0		;137

	0		;140
P1 164,364		;141 a (cAt)
P  160			;142 b
P  010			;143 c
P  040			;144 d (noTifiy)
P2 334,100,200,000	;145 e (tEn) EH3 SUPPRESSED FOR HARDWARE BUG.
P  270			;146 f
P  070			;147 g

P  330			;150 h
P3 344,320,120,220	;151 i
P  130			;152 j
P  230			;153 k
P  030			;154 l
P  060			;155 m
P  050			;156 n (siNG)
P1 350,150		;157 o (gOt)

P  244			;160 p
	0		;161
P2 134,324,154		;162 r
P  210			;163 s
P  124			;164 t
P3 314,114,214,304	;165 u (rUn)
P  360			;166 v
P  264			;167 w

P  034			;170 x (THose)
P1 224,104		;171 y
P  340			;172 z (aZure)
	0		;173
	0		;174
	0		;175
	0		;176
	0		;177
;Phoneme modifier table

COMMENT⊗

The digits 1-3 after a vowel select shorter versions of the
basic phoneme.  The base code is in the first 9 bits of the conversion
table entry, and the shorter versions are in successive 9-bit bytes.
If you use a digit that is larger than the highest-numbered version
of the phoneme, you will get the highest-numbered one that exists.
⊗

MODTAB:	POINT 9,LAST,8			;Base phoneme
	POINT 9,LAST,17			;Mod 1
	POINT 9,LAST,26			;Mod 2
	POINT 9,LAST,35			;Mod 3

VBUF:	BLOCK 3
BUFR:	BLOCK =23

END